package com.tjc.ratelimit;

/**
 * @Author: tjc
 * @description
 * @Date Created in 0:03 2022-02-21
 * 漏桶
 */
class LeakyBucketPolicy implements RateLimitPolicy {
    private int leftQuota;
    private long leakingRate;
    private int capacity;
    private long currentTime;

    public LeakyBucketPolicy(int leftQuota, long leakingRate, int capacity) {
        this.leftQuota = leftQuota;
        this.leakingRate = leakingRate;
        this.capacity = capacity;
        this.currentTime = System.currentTimeMillis();
    }

    @Override
    public synchronized boolean access(String serviceName) {
        long reqMillis = System.currentTimeMillis();
        return watering(reqMillis, 1);
    }

    private boolean watering(long reqMillis, int quota) {
        makeSpace(reqMillis);
        if (leftQuota + quota > capacity) {
            return false;
        } else {
            leftQuota += quota;
            return true;
        }
    }

    private void makeSpace(long reqMillis) {
        long interval = reqMillis - currentTime;
        int flow = (int) (interval / leakingRate);
        leftQuota -= flow;
        leftQuota = leftQuota > 0 ? leftQuota : 0;
        currentTime = reqMillis;
    }
}
